package me.yxy.mobanddd.controller;

import me.yxy.mobanddd.components.AppContext;
import me.yxy.mobanddd.controller.request.command.AddOrderToShipmentRequest;
import me.yxy.mobanddd.controller.request.command.AddShipmentWithTransportRequest;
import me.yxy.mobanddd.controller.request.command.ShipmentAwareBaseRequest;
import me.yxy.mobanddd.controller.response.CommandResponse;
import me.yxy.mobanddd.domain.events.ShipmentOrdersChangedEvent;
import me.yxy.mobanddd.domain.shipment.*;
import me.yxy.mobanddd.domain.transportorder.TransportOrder;
import me.yxy.mobanddd.domain.transportorder.TransportOrderRepository;
import me.yxy.mobanddd.domain.transportorder.TransportOrderStatus;
import me.yxy.mobanddd.exception.BusinessException;
import me.yxy.mobanddd.finder.ShipmentFinder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Optional;

@RestController
@RequestMapping("/shipment")
@ResponseBody
@SuppressWarnings("unused")
public class ShipmentEntrance {

    static final Logger logger = LoggerFactory.getLogger(ShipmentEntrance.class);

    /**
     * 根据初始化传入的运单信息来创建调度单
     * @param request
     * @return
     */
    @PostMapping("/createWithTransports")
    @Transactional
    public String createShipmentWithTransportOrders(@RequestBody AddShipmentWithTransportRequest request){

        Shipment newShipment = shipmentFactory.createWithTransportOrders(request.getTransportOrderIds());
        return newShipment.getId()+"";
    }


    /**
     * 确认调度单
     * @param request
     * @return
     */
    @PostMapping("/comfirm")
    @Transactional
    public CommandResponse comfirm(@RequestBody ShipmentAwareBaseRequest request){

        Optional<Shipment> shipmentOp = shipmentRepository.findById(request.getShipmentId());
        Shipment order = shipmentOp.orElseThrow(()->new BusinessException("调度单不存在"));

        order.comfirm();

//        Shipment newShipment = shipmentFactory.createWithTransportOrders(request.getTransportOrderIds());
//        return newShipment.getId()+"";
        return CommandResponse.ok();
    }



    @PostMapping("/addOrder")
    @Transactional
    public CommandResponse addOrderToShipment(@RequestBody AddOrderToShipmentRequest request){

        //获取调度单
        Optional<Shipment> shipmentOp = shipmentRepository.findById(request.getShipmentId());
        Shipment shipment = shipmentOp.orElseThrow(()->new BusinessException("调度单不存在"));

        //调度单的状态必须是非运抵
        if (shipment.getStatus() == ShipmentStatus.CANCELLED || shipment.getStatus() == ShipmentStatus.FINISHED) {
            throw new BusinessException("调度单当前状态不允许修改配载信息");
        }

        //检查这些运单没有被加入到运单中
        Integer hasBoundShipmentCount = transportOrderRepository.countIfhasShipment(request.getOrderIds());
        if(hasBoundShipmentCount>0){
            throw new BusinessException("已经有运单绑定到其他调度单，无法添加");
        }

        /*
           批量绑定运单

           按之前的原则，代码量不大的时候，就把这里当作 DomainService来做，代码是允许写在这里的
         */
        Iterable<TransportOrder> transportOrders = transportOrderRepository.findAllById(request.getOrderIds());
        for (TransportOrder transportOrder : transportOrders) {
            transportOrder.setShipment(shipment);
            transportOrder.setStatus(TransportOrderStatus.READY);
        }

        //广播事件
        AppContext.eventMachine().publish(new ShipmentOrdersChangedEvent(this,shipment.getId()));
        return CommandResponse.ok();

    }

    /**
     * 从调度单中移除若干运单
     * @param request
     * @return
     */
    @PostMapping("/removeOrders")
    @Transactional
    public CommandResponse removeTransportOrders(@RequestBody AddOrderToShipmentRequest request){

        //首先定位调度单
        Optional<Shipment> shipmentOp = shipmentRepository.findById(request.getShipmentId());
        Shipment shipment = shipmentOp.orElseThrow(()->new BusinessException("调度单不存在"));

        //调度单的状态必须是非运抵
        if (shipment.getStatus() == ShipmentStatus.CANCELLED || shipment.getStatus() == ShipmentStatus.FINISHED) {
            throw new BusinessException("调度单当前状态不允许修改配载信息");
        }

        //判断状态，未运抵之前的运单都可以被移除
        Integer finishedCount = transportOrderRepository.countIfFinished(TransportOrderStatus.FINISHED,request.getOrderIds());
        if(finishedCount>0){
            throw new BusinessException("已经有运单运抵，无法执行删除流程");
        }

        //分别将运单移除出去
        Iterable<TransportOrder> transportOrders = transportOrderRepository.findAllById(request.getOrderIds());
        for (TransportOrder transportOrder : transportOrders) {
            transportOrder.setShipment(null);
            transportOrder.setStatus(TransportOrderStatus.INIT);
        }

        //发布调度单明细变动事件
        AppContext.eventMachine().publish(new ShipmentOrdersChangedEvent(this,shipment.getId()));

        return CommandResponse.ok();
    }

    @Autowired
    ShipmentFinder shipmentFinder;

    @Autowired
    ShipmentRepository shipmentRepository;

    @Autowired
    TransportOrderRepository transportOrderRepository;

    @Autowired
    ShipmentFactory shipmentFactory;


    @Autowired
    ShipmentComfirmSupporter shipmentComfirmService;
}
